/**
 * 字符串混淆和还原工具
 */

/**
 * 默认字符集，用于插入混淆字符
 */
const DEFAULT_CHARSET =
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

/**
 * 对字符串进行混淆处理
 * @param str 需要混淆的字符串
 * @param interval 插入混淆字符的间隔，默认为10
 * @param charset 用于混淆的字符集，默认为字母和数字
 * @returns 混淆后的字符串
 */
export function obfuscate(
  str: string,
  interval: number = 10,
  charset: string = DEFAULT_CHARSET,
): string {
  if (typeof str !== 'string') {
    throw new Error('Input must be a string');
  }

  if (interval <= 0) {
    throw new Error('Interval must be a positive integer');
  }

  if (!charset || typeof charset !== 'string') {
    throw new Error('Charset must be a non-empty string');
  }

  const strLength = str.length;
  if (strLength === 0) {
    return `#${interval}#`;
  }

  // 计算需要插入的混淆字符数量
  const insertCount = Math.floor((strLength - 1) / interval);

  // 预先计算结果数组的大小
  const resultSize = strLength + insertCount + String(interval).length + 2;

  // 使用数组来构建结果，提高性能
  const result: string[] = new Array(resultSize);
  let resultIndex = 0;

  // 添加步长信息
  result[resultIndex++] = '#';
  const intervalStr = String(interval);
  for (let i = 0; i < intervalStr.length; i++) {
    result[resultIndex++] = intervalStr[i];
  }
  result[resultIndex++] = '#';

  // 添加字符串内容和混淆字符
  const charsetLength = charset.length;
  for (let i = 0; i < strLength; i++) {
    result[resultIndex++] = str[i];

    // 每隔指定长度插入一个随机字符（不在最后一个字符后插入）
    if ((i + 1) % interval === 0 && i < strLength - 1) {
      const randomIndex = Math.floor(Math.random() * charsetLength);
      result[resultIndex++] = charset[randomIndex];
    }
  }

  return result.join('');
}

/**
 * 还原混淆的字符串
 * @param str 混淆后的字符串
 * @returns 还原后的原始字符串
 */
export function deobfuscate(str: string): string {
  if (typeof str !== 'string') {
    return str as unknown as string;
  }

  // 解析步长信息
  const stepEndIndex = str.indexOf('#', 1);
  if (stepEndIndex <= 1) {
    throw new Error('Invalid obfuscated string format');
  }

  const stepStr = str.substring(1, stepEndIndex);
  const step = parseInt(stepStr, 10);
  if (Number.isNaN(step) || step <= 0) {
    throw new Error('Invalid step value in obfuscated string');
  }

  // 获取去除步长信息的内容
  const content = str.substring(stepEndIndex + 1);
  const contentLength = content.length;

  if (contentLength === 0) {
    return '';
  }

  // 计算原始字符串长度
  const originalLength =
    contentLength - Math.floor((contentLength - 1) / (step + 1));
  const result: string[] = new Array(originalLength);
  let resultIndex = 0;

  // 还原原始字符串，跳过混淆字符
  for (let i = 0; i < contentLength; i++) {
    // 跳过混淆字符（每隔step+1个字符中的最后一个）
    if (i % (step + 1) === step) {
      continue;
    }
    result[resultIndex++] = content[i];
  }

  return result.join('');
}
